#include <stdint.h> // 标准整数类型头文件
#include <string.h> // 字符串操作头文件

// 主功能模块头文件
#include "usbip_server.h"       // USBIP服务器主头文件
#include "dap_main.h"         // DAP（调试访问端口）处理头文件
#include "wifi_configuration.h" // WiFi配置头文件

// USBIP组件
#include "usb_handle.h"     // USB设备处理头文件
#include "usb_descriptor.h" // USB描述符头文件

// LwIP网络栈
#include "lwip/err.h"     // LWIP错误处理头文件
#include "lwip/sockets.h" // LWIP套接字头文件
#include "lwip/sys.h"     // LWIP系统头文件
#include <lwip/netdb.h>   // LWIP网络数据库头文件

// 优化分支预测的宏
#ifndef likely
#define likely(x) __builtin_expect(!!(x), 1) // 很可能为真
#endif
#ifndef unlikely
#define unlikely(x) __builtin_expect(!!(x), 0) // 很可能为假
#endif

/* ========== 辅助函数声明 ========== */
// Attach阶段辅助函数
static int read_stage1_command(uint8_t *buffer, uint32_t length);   // 读取Stage1命令
static void handle_device_list(uint8_t *buffer, uint32_t length);   // 处理设备列表请求
static void handle_device_attach(uint8_t *buffer, uint32_t length); // 处理设备附加请求
static void send_stage1_header(uint16_t command, uint32_t status);  // 发送Stage1响应头
static void send_device_list();                                     // 发送设备列表
static void send_device_info();                                     // 发送设备信息
static void send_interface_info();                                  // 发送接口信息

// URB处理辅助函数
static void pack(void *data, int size);   // 数据打包（主机序转网络序）
static void unpack(void *data, int size); // 数据解包（网络序转主机序）

// Unlink请求处理
static void handle_unlink(usbip_stage2_header *header);          // 处理UNLINK请求
static void send_stage2_unlink(usbip_stage2_header *req_header); // 发送UNLINK响应

/* ========== 网络发送函数 ========== */
int usbip_network_send(int s, const void *dataptr, size_t size, int flags)
// 根据编译选项选择不同的网络发送方式
{
#if (USE_KCP == 1)
    return kcp_network_send(dataptr, size); // 使用KCP协议发送
#elif (USE_TCP_NETCONN == 1)
    return tcp_netconn_send(dataptr, size); // 使用TCP Netconn API发送
#else
    return send(s, dataptr, size, flags); // 使用标准BSD socket发送
#endif
}

/* ========== Attach阶段处理 ========== */
// 处理Attach阶段的命令
static int attach(uint8_t *buffer, uint32_t length)
{
    // 1. 从缓冲区读取命令
    int command = read_stage1_command(buffer, length);
    if (command < 0)
        return -1; // 命令无效

    // 2. 根据命令类型处理
    switch (command) {
        case USBIP_STAGE1_CMD_DEVICE_LIST: // 0x8005: 请求设备列表
            handle_device_list(buffer, length);
            break;
        case USBIP_STAGE1_CMD_DEVICE_ATTACH: // 0x8003: 请求附加设备
            handle_device_attach(buffer, length);
            break;
        default:
            os_printf("attach Unknown command: %d\r\n", command); // 未知命令
            break;
    }
    return 0;
}

// 从缓冲区读取Stage1命令（前2字节）
static int read_stage1_command(uint8_t *buffer, uint32_t length)
{
    if (length < sizeof(usbip_stage1_header))
        return -1; // 长度不足
    usbip_stage1_header *req = (usbip_stage1_header *)buffer;
    return (ntohs(req->command) & 0xFF); // 取命令低字节（网络序转主机序）
}

// 处理设备列表请求
static void handle_device_list(uint8_t *buffer, uint32_t length)
{
    os_printf("Handling dev list request...\r\n");
    // 发送响应头 + 设备列表
    send_stage1_header(USBIP_STAGE1_CMD_DEVICE_LIST, 0); // 状态0=成功
    send_device_list();
}

// 处理设备附加请求
static void handle_device_attach(uint8_t *buffer, uint32_t length)
{
    os_printf("Handling dev attach request...\r\n");
    // 验证长度（应包含总线ID）
    if (length < sizeof(USBIP_BUSID_SIZE)) {
        os_printf("handle device attach failed!\r\n");
        return;
    }
    // 发送响应头 + 设备详情
    send_stage1_header(USBIP_STAGE1_CMD_DEVICE_ATTACH, 0);
    send_device_info();
}

// 发送Stage1响应头（通用结构）
static void send_stage1_header(uint16_t command, uint32_t status)
{
    os_printf("Sending header...\r\n");
    usbip_stage1_header header;
    header.version = htons(273); // USBIP协议版本号（固定值273）
    header.command = htons(command);
    header.status = htonl(status); // 状态码
    usbip_network_send(kSock, (uint8_t *)&header, sizeof(usbip_stage1_header), 0);
}

// 发送设备列表（当前仅支持一个设备）
static void send_device_list()
{
    os_printf("Sending device list...\r\n");
    usbip_stage1_response_devlist response_devlist;
    response_devlist.list_size = htonl(1); // 设备数量=1
    usbip_network_send(kSock, (uint8_t *)&response_devlist, sizeof(response_devlist), 0);

    // 发送该设备的详细信息
    send_device_info();
    send_interface_info(); // 发送接口信息
}

// 发送设备详细信息
static void send_device_info()
{
    os_printf("Sending device info...\r\n");
    usbip_stage1_usb_device device;
    // 填充设备路径和总线ID
    strcpy(device.path, "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1");
    strcpy(device.busid, "1-1");
    // 设备标识信息（需转为网络字节序）
    device.busnum = htonl(1);
    device.devnum = htonl(1);
    device.speed = htonl(3); // USB_SPEED_HIGH=3
    // 厂商/产品信息（从描述符获取）
    device.idVendor = htons(USBD0_DEV_DESC_IDVENDOR);
    device.idProduct = htons(USBD0_DEV_DESC_IDPRODUCT);
    device.bcdDevice = htons(USBD0_DEV_DESC_BCDDEVICE);
    // 设备类/子类/协议
    device.bDeviceClass = 0x00; // 自定义设备类
    device.bDeviceSubClass = 0x00;
    device.bDeviceProtocol = 0x00;
    // 配置信息
    device.bConfigurationValue = 1; // 当前配置
    device.bNumConfigurations = 1;  // 配置数量
    device.bNumInterfaces = 1;      // 接口数量
    usbip_network_send(kSock, (uint8_t *)&device, sizeof(device), 0);
}

// 发送接口信息
static void send_interface_info()
{
    os_printf("Sending interface info...\r\n");
    usbip_stage1_usb_interface interface;
    // 从描述符获取接口类/子类/协议
    interface.bInterfaceClass = USBD_CUSTOM_CLASS0_IF0_CLASS;
    interface.bInterfaceSubClass = USBD_CUSTOM_CLASS0_IF0_SUBCLASS;
    interface.bInterfaceProtocol = USBD_CUSTOM_CLASS0_IF0_PROTOCOL;
    interface.padding = 0; // 必须为0
    usbip_network_send(kSock, (uint8_t *)&interface, sizeof(interface), 0);
}

/* ========== URB（USB请求块）处理核心 ========== */
static int usbip_urb_process(uint8_t *base, uint32_t length)
{
    usbip_stage2_header *header = (usbip_stage2_header *)base;
    uint8_t *data;
    uint32_t command, dir, ep;
    uint32_t unlink_count = 0; // UNLINK请求计数器
    bool may_has_data;         // 标记请求是否包含数据
    int sz, ret;
    int dap_req_num = 0; // DAP请求计数器

    while (1) {
        // 1. 读取URB头（固定48字节）
        data = base;
        sz = 48; // sizeof(usbip_stage2_header)
        do {
            ret = recv(kSock, data, sz, 0);
            if (ret <= 0)
                goto out; // 错误或连接关闭
            sz -= ret;
            data += ret;
        } while (sz > 0);

        // 解析关键字段（转为主机字节序）
        command = ntohl(header->base.command);
        dir = ntohl(header->base.direction);
        ep = ntohl(header->base.ep);
        // OUT方向请求可能携带数据
        may_has_data = (command == USBIP_STAGE2_REQ_SUBMIT && dir == USBIP_DIR_OUT);
        sz = may_has_data ? ntohl(header->u.cmd_submit.data_length) : 0;

        // 2. 读取数据负载（如果有）
        while (sz) {
            ret = recv(kSock, data, sz, 0);
            if (ret <= 0)
                goto out;
            sz -= ret;
            data += ret;
        }

        // 3. 根据命令类型处理URB
        if (likely(command == USBIP_STAGE2_REQ_SUBMIT)) {
            // 处理SUBMIT请求
            if (likely(ep == 1 && dir == USBIP_DIR_IN)) {
                // EP1 IN: DAP响应（快速回复）
                fast_reply(base, sizeof(usbip_stage2_header), dap_req_num);
                if (dap_req_num > 0)
                    dap_req_num--;
            } else if (likely(ep == 1 && dir == USBIP_DIR_OUT)) {
                // EP1 OUT: DAP请求
                dap_req_num++;
                handle_dap_data_request(header, length);
            } else if (ep == 0) {
                // EP0: 控制传输
                unpack(base, sizeof(usbip_stage2_header)); // 解包头部
                handleUSBControlRequest(header);           // 处理控制请求
            } else {
                // 其他端点（如EP3用于SWO调试）
                os_printf("ep reserved:%d\r\n", ep);
                send_stage2_submit(header, 0, 0); // 空响应
            }
        } else if (command == USBIP_STAGE2_REQ_UNLINK) {
            // 处理UNLINK请求（取消异步URB）
            if (unlink_count == 0 || unlink_count % 100 == 0)
                os_printf("unlink\r\n");
            unlink_count++;
            unpack(base, sizeof(usbip_stage2_header)); // 解包头部
            handle_unlink(header);                     // 处理取消逻辑
        } else {
            // 未知命令
            os_printf("emulate unknown command:%d\r\n", command);
            return -1;
        }
    }

out:
    if (ret < 0)
        os_printf("recv failed: errno %d\r\n", errno);
    return ret;
}

/* ========== USBIP主工作循环 ========== */
int usbip_worker(uint8_t *base, uint32_t length, enum usbip_server_state_t *state)
{
    uint8_t *data;
    int pre_read_sz = 4; // 预读字节数（用于状态恢复）
    int sz, ret;
    /*     主机查询设备列表请求      */
    // 状态机处理
    if (*state == WAIT_DEVLIST) {
        // 1. 等待设备列表请求（补全8字节头部）
        data = base + 4; // 已读前4字节
        sz = 8 - pre_read_sz;
        do {
            ret = recv(kSock, data, sz, 0);
            if (ret <= 0)
                return ret;
            sz -= ret;
            data += ret;
        } while (sz > 0);

        // 处理设备列表请求
        ret = attach(base, 8);
        if (ret)
            return ret;
        pre_read_sz = 0; // 重置预读计数
    }
    // todo 客户端选择设备后，发送 USBIP_STAGE1_CMD_DEVICE_ATTACH（0x8003），与目标设备建立远程连接。
    // todo 根据客户端请求中指定的设备 ID，选择对应的设备描述符。
    //  2. 等待设备附加请求（固定40字节）
    *state = WAIT_IMPORT;
    data = base + pre_read_sz;
    sz = 40 - pre_read_sz;
    do {
        ret = recv(kSock, data, sz, 0);
        if (ret <= 0)
            return ret;
        sz -= ret;
        data += ret;
    } while (sz > 0);

    // 处理设备附加请求
    ret = attach(base, 40);
    if (ret)
        return ret;

    // 3. 进入URB处理循环
    *state = WAIT_URB;
    ret = usbip_urb_process(base, length);
    if (ret) {
        *state = WAIT_DEVLIST; // 出错则重置状态
        return ret;
    }

    return 0;
}

/* ========== 字节序转换工具 ========== */
// 数据打包（主机字节序 -> 网络字节序）
static void pack(void *data, int size)
{
    // 跳过setup字段（8字节），处理剩余4字节对齐部分
    int sz = (size / sizeof(uint32_t)) - 2; // 减去setup的8字节（2个uint32）
    uint32_t *ptr = (uint32_t *)data;
    for (int i = 0; i < sz; i++) {
        ptr[i] = htonl(ptr[i]); // 逐字转换
    }
}

// 数据解包（网络字节序 -> 主机字节序）
static void unpack(void *data, int size)
{
    // 同上，跳过setup字段
    int sz = (size / sizeof(uint32_t)) - 2;
    uint32_t *ptr = (uint32_t *)data;
    for (int i = 0; i < sz; i++) {
        ptr[i] = ntohl(ptr[i]);
    }
}

/* ========== Stage2响应函数 ========== */
// 发送SUBMIT响应（无数据）
void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length)
{
    // 设置响应类型和方向（IN/OUT反转）
    req_header->base.command = USBIP_STAGE2_RSP_SUBMIT;
    req_header->base.direction = !(req_header->base.direction);
    // 清空返回结构并填充状态/数据长度
    memset(&(req_header->u.ret_submit), 0, sizeof(usbip_stage2_header_ret_submit));
    req_header->u.ret_submit.status = status;
    req_header->u.ret_submit.data_length = data_length;
    // 打包并发送
    pack(req_header, sizeof(usbip_stage2_header));
    usbip_network_send(kSock, req_header, sizeof(usbip_stage2_header), 0);
}

// 发送SUBMIT响应（带数据）
void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length)
{
    // 先发送头部
    send_stage2_submit(req_header, status, data_length);
    // 再发送数据负载
    if (data_length) {
        usbip_network_send(kSock, data, data_length, 0);
    }
}

// 快速发送SUBMIT响应（合并头部和数据）
void send_stage2_submit_data_fast(usbip_stage2_header *req_header, const void *const data, int32_t data_length)
{
    uint8_t *send_buf = (uint8_t *)req_header;
    // 直接设置网络字节序字段
    req_header->base.command = PP_HTONL(USBIP_STAGE2_RSP_SUBMIT); // 宏转换
    req_header->base.direction = htonl(!(req_header->base.direction));
    // 填充返回结构
    memset(&(req_header->u.ret_submit), 0, sizeof(usbip_stage2_header_ret_submit));
    req_header->u.ret_submit.data_length = htonl(data_length);
    // 拷贝数据到缓冲区末尾
    if (data)
        memcpy(&send_buf[sizeof(usbip_stage2_header)], data, data_length);
    // 合并发送（头部+数据）
    usbip_network_send(kSock, send_buf, sizeof(usbip_stage2_header) + data_length, 0);
}

/* ========== UNLINK处理 ========== */
// 处理UNLINK请求
static void handle_unlink(usbip_stage2_header *header)
{
    handle_dap_unlink();        // DAP模块取消处理
    send_stage2_unlink(header); // 发送响应
}

// 发送UNLINK响应
static void send_stage2_unlink(usbip_stage2_header *req_header)
{
    // 设置响应类型和方向
    req_header->base.command = USBIP_STAGE2_RSP_UNLINK;
    req_header->base.direction = USBIP_DIR_OUT;
    // 清空返回结构并填充状态（非零表示成功取消）
    memset(&(req_header->u.ret_unlink), 0, sizeof(usbip_stage2_header_ret_unlink));
    req_header->u.ret_unlink.status = -1; // -ECONNRESET语义
    // 打包并发送
    pack(req_header, sizeof(usbip_stage2_header));
    usbip_network_send(kSock, req_header, sizeof(usbip_stage2_header), 0);
}